using System;
using System.Text;
using System.Web.Mvc;


namespace DigitallyCreated.Utilities.Mvc
{
	/// <summary>
	/// The CollapsibleFieldset creates a fieldset and legend that collapses when the user clicks on the
	/// legend and expands back into existence when the legend is clicked again. The class is 
	/// <see cref="IDisposable"/> and therefore can be used in a using block, and when the using block ends
	/// a closing <c>fieldset</c> tag will be outputted.
	/// </summary>
	/// <remarks>
	/// <para>
	/// The easiest way to use this class is by using the 
	/// <see cref="EyeCandyHtmlHelpers.CollapsibleFieldset"/> extension method.
	/// </para>
	/// <para>
	/// This method will output XHTML that looks like this:
	/// </para>
	/// <code><![CDATA[
	/// <fieldset id="UniqueAutoGeneratedIdGoesHere" class="Collapsible">
	///		<legend class="Expand|Collapse"><a>Your legend text here.</a></legend>
	/// 
	///		
	/// </fieldset>
	/// ]]></code>
	/// <para>
	/// Note that each time you call this method a new unique ID is auto-generated and used on the
	/// fieldset. Also note that the legend will have either the <c>Expand</c> or the <c>Collapse</c>CSS
	/// class if clicking it will expand it or collapse it, respectively.
	/// </para>
	/// <para>
	/// This HTML is entirely unstyled. You will need to style it to suit your website in your own CSS
	/// file.
	/// </para>
	/// <para>
	/// The collapse effect is done using jQuery 1.3.2 (this comes with ASP.NET MVC in the standard  Visual
	/// Studio ASP.NET MVC project template). You need to ensure it is included on your page.
	/// </para>
	/// </remarks>
	public class CollapsibleFieldset : IDisposable
	{
		private readonly HtmlHelper _Html;


		/// <summary>
		/// Constructor, creates a <see cref="CollapsibleFieldset"/> and outputs the fieldset opening tag and
		/// legend tag immediately.
		/// </summary>
		/// <param name="html">The page's <see cref="HtmlHelper"/></param>
		/// <param name="legendText">The text to display in the legend</param>
		/// <param name="collapsedByDefault">Whether or not the fieldset is collapsed by default</param>
		public CollapsibleFieldset(HtmlHelper html, string legendText, bool collapsedByDefault)
		{
			_Html = html;
			WriteStart(legendText, collapsedByDefault);
		}


		/// <summary>
		/// Writes the start tags and JavaScript
		/// </summary>
		/// <param name="legendText">The text to display in the legend</param>
		/// <param name="collapsedByDefault">Whether or not the fieldset is collapsed by default</param>
		private void WriteStart(string legendText, bool collapsedByDefault)
		{
			string id = "GUID" + Guid.NewGuid().ToString("N");
			string js = CreateJavaScript(id, collapsedByDefault);

			TagBuilder fieldset = new TagBuilder("fieldset");
			fieldset.AddCssClass("Collapsible");
			fieldset.Attributes["id"] = id;
			
			
			TagBuilder legend = new TagBuilder("legend");
			legend.AddCssClass("Collapse");
			legend.InnerHtml = String.Format("<a>{0}</a>", _Html.Encode(legendText));
			

			_Html.ViewContext.HttpContext.Response.Write(js);
			_Html.ViewContext.HttpContext.Response.Write(fieldset.ToString(TagRenderMode.StartTag));
			_Html.ViewContext.HttpContext.Response.Write(legend.ToString());
		}


		/// <summary>
		/// Creates the JavaScript that controls the collapsing
		/// </summary>
		/// <param name="id">The unique ID for the fieldset</param>
		/// <param name="collapsedByDefault">Whether or not the fieldset is collapsed by default</param>
		/// <returns>The JavaScript inside a script tag</returns>
		private string CreateJavaScript(string id, bool collapsedByDefault)
		{
			StringBuilder js = new StringBuilder();

			js.Append(@"
				jQuery(function()
				{
					var func = function(speed)
					{
						var legend = jQuery(""#<<id>> legend"");
						legend.parent().children().not(""legend"").toggle(speed);

						if (legend.hasClass(""Collapse""))
						{
							legend.removeClass(""Collapse"");
							legend.addClass(""Expand"");
						}
						else
						{
							legend.removeClass(""Expand"");
							legend.addClass(""Collapse"");
						}
					}

					<<collapse>>

					jQuery(""#<<id>> legend"").click(function() { func(""fast""); });
				});
			");

			js.Replace("<<id>>", id);
			if (collapsedByDefault)
				js.Replace("<<collapse>>", "func(0);");
			else
				js.Replace("<<collapse>>", String.Empty);

			TagBuilder script = new TagBuilder("script");
			script.Attributes["type"] = "text/javascript";
			script.InnerHtml = js.ToString();

			return script.ToString();
		}


		/// <summary>
		/// Writes the closing fieldset tag
		/// </summary>
		public void Dispose()
		{
			_Html.ViewContext.HttpContext.Response.Write("</fieldset>");
		}
	}
}